home *** CD-ROM | disk | FTP | other *** search
/ Light ROM 1 / LIGHT-ROM 1 (Amiga Library Services)(1994).iso / ffdisks / d902.lha / Less / Source / source.lha / signal.c < prev    next >
C/C++ Source or Header  |  1993-02-18  |  6KB  |  256 lines

  1. /*
  2.  * Routines dealing with signals.
  3.  *
  4.  * A signal usually merely causes a bit to be set in the "signals" word.
  5.  * At some convenient time, the mainline code checks to see if any
  6.  * signals need processing by calling psignal().
  7.  * An exception is made if we are reading from the keyboard when the
  8.  * signal is received.  Some operating systems will simply call the
  9.  * signal handler and NOT return from the read (with EINTR).
  10.  * To handle this case, we service the interrupt directly from
  11.  * the handler if we are reading from the keyboard.
  12.  */
  13.  
  14. #ifdef AMIGA
  15. /*
  16.  * This all works on the Amiga under SAS-C.  The SIGINT stuff only
  17.  * responds to ^C from the window that started Less, not the Less window
  18.  * itself.  ^C from the Less window is polled by chk_sigs(), and
  19.  * eventually does the same thing.
  20.  */
  21.  
  22. #define SIGWINCH
  23. #define S_WINCH 04
  24. #endif
  25.  
  26. #include "less.h"
  27.  
  28. #include <signal.h>
  29. #include <setjmp.h>
  30.  
  31. /*
  32.  * The type of signal handler functions.
  33.  * Usually int, although it should be void.
  34.  */
  35. #ifdef AMIGA
  36. typedef void            HANDLER;
  37. #else
  38. typedef int             HANDLER;
  39. #endif
  40.  
  41. /* Prototypes for functions defined in signal.c */
  42.  
  43. static HANDLER interrupt __PROTO((void));
  44.  
  45.  
  46. /*
  47.  * "sigs" contains bits indicating signals which need to be processed.
  48.  */
  49. public int sigs;
  50. #ifndef AMIGA /* This is in Less.h for Amiga, since shared with io.c */
  51. #define S_INTERRUPT     01
  52. #endif
  53. #ifdef SIGTSTP
  54. #define S_STOP          02
  55. #endif
  56.  
  57.  
  58. extern int reading;
  59. extern int sc_width, sc_height;
  60. extern char *first_cmd;
  61. extern jmp_buf main_loop;
  62.  
  63. /*
  64.  * Interrupt signal handler.
  65.  */
  66. #ifdef __STDC__
  67. static HANDLER interrupt (void)
  68. #else
  69.         static HANDLER
  70. interrupt()
  71. #endif
  72. {
  73. #ifdef AMIGA
  74.         /* This gets entered upon ^C from the CLI window.  ^C in the
  75.          * Less window is handled in io.c.  A ^C in the CLI window is
  76.          * taken as a real sign of distress, we quit.
  77.          * (Sending less a break from another process gets here, too.
  78.          */
  79.         quit();
  80. #else
  81.         SIGNAL(SIGINT, interrupt);
  82.         sigs |= S_INTERRUPT;
  83.         if (reading)
  84.                 psignals();
  85. #endif
  86. }
  87.  
  88. #ifdef SIGTSTP
  89. /*
  90.  * "Stop" (^Z) signal handler.
  91.  */
  92.         static HANDLER
  93. stop()
  94. {
  95.         SIGNAL(SIGTSTP, stop);
  96.         sigs |= S_STOP;
  97.         if (reading)
  98.                 psignals();
  99. }
  100. #endif
  101.  
  102. #ifdef SIGWINCH
  103. /*
  104.  * "Window" change handler
  105.  */
  106. #ifdef __STDC__
  107. void winch (void)
  108. #else
  109. winch()
  110. #endif
  111. {
  112. #ifndef AMIGA
  113.         SIGNAL(SIGWINCH, winch);
  114. #endif
  115.         sigs |= S_WINCH;
  116.         if (reading)
  117.                 psignals();
  118. #ifdef AMIGA
  119.         else
  120.                 sigs |= S_INTERRUPT;
  121. #endif
  122. }
  123. #else
  124. #ifdef SIGWIND
  125. /*
  126.  * "Window" change handler
  127.  */
  128. winch()
  129. {
  130.         SIGNAL(SIGWIND, winch);
  131.         sigs |= S_WINCH;
  132.         if (reading)
  133.                 psignals();
  134. }
  135. #endif
  136. #endif
  137.  
  138. /*
  139.  * Set up the signal handlers.
  140.  */
  141. #ifdef __STDC__
  142. void init_signals (void)
  143. #else
  144.         public void
  145. init_signals()
  146. #endif
  147. {
  148.         (void) SIGNAL(SIGINT, interrupt);
  149. #ifdef SIGTSTP
  150.         (void) SIGNAL(SIGTSTP, stop);
  151. #endif
  152. #ifdef SIGWINCH
  153. #ifndef AMIGA
  154.         (void) SIGNAL(SIGWINCH, winch);
  155. #endif
  156. #else
  157. #ifdef SIGWIND
  158.         (void) SIGNAL(SIGWIND, winch);
  159. #endif
  160. #endif
  161. }
  162.  
  163. /*
  164.  * Process any signals we have recieved.
  165.  * A received signal cause a bit to be set in "sigs".
  166.  */
  167. #ifdef __STDC__
  168. void psignals (void)
  169. #else
  170.         public void
  171. psignals()
  172. #endif
  173. {
  174.         register int tsignals;
  175.  
  176.         tsignals = sigs;
  177.         sigs = 0;
  178.         if (tsignals == 0)
  179.                 return;
  180.  
  181.         dropout();              /* Discard any buffered output */
  182.  
  183. #ifdef S_WINCH
  184.         if (tsignals & S_WINCH)
  185.         {
  186.                 int old_width, old_height;
  187.                 /*
  188.                  * Re-execute get_term() to read the new window size.
  189.                  */
  190.                 old_width = sc_width;
  191.                 old_height = sc_height;
  192.                 get_term();
  193.                 if (sc_width != old_width || sc_height != old_height)
  194.                         first_cmd = "r";
  195. #ifndef AMIGA
  196.                 longjmp(main_loop, 1);
  197. #endif
  198.         }
  199. #endif
  200. #ifdef SIGTSTP
  201.         if (tsignals & S_STOP)
  202.         {
  203.                 /*
  204.                  * Clean up the terminal.
  205.                  */
  206. #ifdef SIGTTOU
  207.                 SIGNAL(SIGTTOU, SIG_IGN);
  208. #endif
  209.                 lower_left();
  210.                 clear_eol();
  211.                 flush();
  212.                 raw_mode(0);
  213. #ifdef SIGTTOU
  214.                 SIGNAL(SIGTTOU, SIG_DFL);
  215. #endif
  216.                 SIGNAL(SIGTSTP, SIG_DFL);
  217. #if SIGSETMASK
  218.                 /*
  219.                  * This system will not allow us to send a
  220.                  * stop signal (SIGTSTP) to ourself
  221.                  * while we are in the signal handler, like maybe now.
  222.                  * (This can be the case if we are reading; see comment above.)
  223.                  * So we ask the silly system for permission to do so.
  224.                  */
  225.                 sigsetmask(0);
  226. #endif
  227.                 kill(getpid(), SIGTSTP);
  228.                 /*
  229.                  * ... Bye bye. ...
  230.                  * Hopefully we'll be back later and resume here...
  231.                  * Reset the terminal and arrange to repaint the
  232.                  * screen when we get back to the main command loop.
  233.                  */
  234.                 SIGNAL(SIGTSTP, stop);
  235.                 raw_mode(1);
  236.                 first_cmd = "r";
  237.                 longjmp(main_loop, 1);
  238.         }
  239. #endif
  240.         if (tsignals & S_INTERRUPT)
  241.         {
  242. #ifdef AMIGA
  243.                 error("Interrupt");
  244. #else
  245.                 bell();
  246.                 /*
  247.                  * {{ You may wish to replace the bell() with
  248.                  *    error("Interrupt"); }}
  249.                  */
  250. #endif
  251.         }
  252.  
  253.         longjmp(main_loop, 1);
  254. }
  255.  
  256.